home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Resource for Source: C/C++
/
Resource for Source - C-C++.iso
/
codelib4
/
v_06_08
/
v6n8037a.txt
< prev
next >
Wrap
Text File
|
1995-11-01
|
29KB
|
806 lines
/******************************************************************************
*
* File: ASCII.H
*
* Contents: Definitions for standard ASCII values
*
******************************************************************************/
#define NUL 0x00
#define SOH 0x01
#define STX 0x02
#define ETX 0x03
#define EOT 0x04
#define ENQ 0x05
#define ACK 0x06
#define BEL 0x07
#define BS 0x08
#define HT 0x09
#define LF 0x0A
#define VT 0x0B
#define FF 0x0C
#define CR 0x0D
#define SO 0x0E
#define SI 0x0F
#define DLE 0x10
#define DC1 0x11
#define DC2 0x12
#define DC3 0x13
#define DC4 0x14
#define NAK 0x15
#define SYN 0x16
#define ETB 0x17
#define CAN 0x18
#define EM 0x19
#define SUB 0x1A
#define ESC 0x1B
#define FS 0x1C
#define GS 0x1D
#define RS 0x1E
#define US 0x1F
#define SP 0x20
#define DEL 0x7F
/******************************************************************************
*
* File: USEFUL.H
*
* Contents: Declarations for USEFUL.LIB functions.
*
* NOTE: USEFUL.LIB contains general purpose functions that are missing
* from STDIO.LIB or that are useful to keep for future use. This
* is only a partial header file.
*
******************************************************************************/
char *bld_ptr(); /* converts a segment token to a pointer */
unsigned bld_sel(); /* converts a pointer to a token (selector) */
char *c_to_plm(); /* C string to PL/M (byte count) string */
int fdelete(); /* delete a file */
int finfo(); /* get info about file (struct finfo_str) */
int faccess(); /* change file access rights */
/*1****************************************************************************
*
* File: SPOOLER.C
*
* Program: Print Spooler Utility (for iRMX 286 OS)
*
* Summary: This print spooler will monitor the spooler directory for
* files. As files are copied to the spooler directory, they
* will be copied to the system printer. After a file has
* been copied to the printer, it will be deleted from the
* spooler directory.
*
* Usage: 1. Run the spooler as a background job under iRMX-286 R2.0:
*
* CREATEDIR :SD:SPOOLER (if not already present)
*
* BACKGROUND(100,100) SPOOLER
*
* Use "SPOOLER.LOG" as the name of the log file for the job.
*
*
* 2. Next, create a logical name for the spooler directory:
*
* ATTACHFILE :SD:SPOOLER AS :SPOOLER:
* (or)
* ATTACHFILE :MASTER:SD/SPOOLER AS :SPOOLER: (RMX-NET)
*
*
* 3. Finally, use the copy command to send files to the spooler:
*
* COPY SRC/ * TO :SPOOLER:
*
* Caveats: The spooler job sets itself up as a SUPER user so that it
* can have access to any file that is copied to the spooler
* directory. Other than sending a form feed control to the
* printer before the start of each new file, the spooler
* does nothing but copy the files directly to the printer.
* All TAB conversions and paging should be performed before
* a file is copied to the spooler directory.
*
* Author: Richard Carver Date: 03/03/88
*
* Revisions:
*
******************************************************************************/
#include <rmx.h> /* RMX system call declarations */
#include <ascii.h> /* ASCII control codes */
#include <stdio.h> /* Standard C Library */
#include <useful.h> /* Useful Functions Library */
/* RMX Condition Codes */
#define E$OK ((unsigned int)0x0000)
#define E$TIME ((unsigned int)0x0001)
#define E$MEM ((unsigned int)0x0002)
/* Wait Times For RMX System Calls */
#define NO_WAIT ((unsigned int)0)
#define WAIT_ONE_SEC ((unsigned int)100)
#define WAIT_TWO_SEC ((unsigned int)200)
#define WAIT_FOREVER ((unsigned int)0xFFFF)
/* Defines for various RMX system calls */
#define THIS_JOB ((unsigned int)1)
#define ROOT_JOB ((unsigned int)3)
#define FIFO_MBX ((unsigned int)0)
#define NO_RESP ((unsigned int)0)
#define READ_ONLY ((unsigned char)1)
#define BUFFERS_TWO ((unsigned char)2)
#define USER_SUPER ((unsigned int)0)
#define ACCESS_DRAU ((unsigned int)15)
/* Miscellaneous Defines */
#define DISABLE ((unsigned char)0x00)
#define NOT_FOUND ((int)-1)
#define PRINTER_NAME ":LP:"
#define SPOOLER_MBX_NAME "\013SPOOLER_MBX"
/* Spooler Command Codes */
#define CMND_CONTINUE ((int)0)
#define CMND_SUSPEND ((int)1)
#define CMND_SHUTDOWN ((int)2)
#define CMND_NEXTFILE ((int)3)
/* Spooler Commands */
char *spooler_cmnds[] = { "continue",
"suspend",
"shutdown",
"nextfile",
NULL };
/* Structure Declarations */
struct dir_entry_str /* RMX Directory Entry Structure */
{
unsigned int fnode;
char fname[14];
};
struct finfo_str /* RMX File Information Structure */
{
unsigned int device_share;
unsigned int number_connections;
unsigned int number_reader;
unsigned int number_writer;
unsigned char share;
unsigned char named_file;
char device_name[14];
unsigned int file_drivers;
unsigned char functions;
unsigned char flags;
unsigned int device_granularity;
unsigned long int device_size;
unsigned int device_connections;
unsigned int file_id;
unsigned char file_type;
unsigned char file_granularity;
unsigned int owner_id;
unsigned long int create_time;
unsigned long int access_time;
unsigned long int modify_time;
unsigned long int file_size;
unsigned long int file_blocks;
char volume_name[6];
unsigned int volume_granularity;
unsigned long int volume_size;
unsigned int accessor_count;
unsigned char owner_access;
};
struct user_ids_str /* RMX User ID Structure */
{
unsigned int length;
unsigned int count;
unsigned int user_id;
}user_ids = {1, 1, USER_SUPER};
struct xhndlr_str /* RMX Exception Handler Structure */
{
void (*xhndlr_addr)();
unsigned char xhndlr_mode;
};
struct spooler_msg_str /* Spooler Message Structure */
{
int cmnd_code;
};
/* Constant & Global Data */
char spooler_dir[] = "\013:sd:spooler";
int spooler_state = CMND_CONTINUE;
main(argc, argv)
int argc;
char *argv[];
{
int command;
unsigned int dummy_mbx;
unsigned int root_tkn;
unsigned int spooler_mbx;
unsigned int rsp_mbx;
unsigned int stat;
unsigned int status;
struct xhndlr_str xhndlr_info;
struct spooler_msg_str *spooler_msg_ptr;
/*9****************************************************************************
* Disable the RMX exception handler.
******************************************************************************/
rq$get$exception$handler(&xhndlr_info, &status);
if (status == E$OK)
{
xhndlr_info.xhndlr_mode = DISABLE;
rq$set$exception$handler(&xhndlr_info, &status);
}
/*9****************************************************************************
* Get the object token for the system's root job. The root job is the
* highest level in the RMX job tree.
******************************************************************************/
if (status == E$OK)
{
root_tkn = rq$get$task$tokens(ROOT_JOB, &status);
}
if (status == E$OK)
{
/*9****************************************************************************
* Lookup the name of the spooler mailbox in the root job's object
* directory. This will be present only if the spooler is already installed.
* NOTE: RMX uses byte count strings (first byte in string is length).
******************************************************************************/
spooler_mbx =
rq$lookup$object(root_tkn, SPOOLER_MBX_NAME, NO_WAIT, &status);
if (status == E$OK)
{
/*9****************************************************************************
* Since the spooler is installed, check to see if there are two command
* line arguments (program name and spooler command). If there is only one
* argument (program name), inform user that the spooler is already running.
* If more than two arguments exist, the program was incorrectly invoked.
******************************************************************************/
if (argc != 2)
{
if (argc == 1)
{
printf("ERROR: Spooler already installed.\n");
}
else
{
printf("ERROR: Invalid invocation.\n");
}
}
else
{
/*9****************************************************************************
* If the command invocation was correct, verify that the command is a
* valid command. If an invalid command, indicate error. If a valid
* command, create a message to send to the spooler. Create a mailbox to
* receive the response from the spooler. The response will use the same
* segment as the message. Send the message to the spooler. If the message
* could not be sent, the spooler is no longer running (it may have been
* deleted by the "kill" utility). Remove the spooler mailbox name from
* the root directory so that the spooler may be re-installed in the future.
* If the message was sent, wait for the response from the spooler. When
* the response has been received, delete the response mailbox and the
* message segment.
******************************************************************************/
command = command_code(argv[1]);
if (command == NOT_FOUND)
{
printf("ERROR: Invalid spooler command.\n");
}
else
{
spooler_msg_ptr =
calloc(1, sizeof(struct spooler_msg_str));
if (spooler_msg_ptr != NULL)
{
spooler_msg_ptr->cmnd_code = command;
rsp_mbx = rq$create$mailbox(FIFO_MBX, &status);
if (status == E$OK)
{
rq$send$message(spooler_mbx,
bld_sel(spooler_msg_ptr), rsp_mbx, &status);
if (status != E$OK)
{
rq$uncatalog$object(
root_tkn, SPOOLER_MBX_NAME, &stat);
}
else
{
rq$receive$message(rsp_mbx,
WAIT_FOREVER, &dummy_mbx, &status);
}
rq$delete$mailbox(rsp_mbx, &stat);
}
free(spooler_msg_ptr);
}
else
{
status = E$MEM;
}
}
}
}
else if (status == E$TIME)
{
/*9****************************************************************************
* If the spooler mailbox name was not found (lookup timed out), then
* the spooler is not installed. If only the program name was entered (one
* command line argument) then this invocation of the program will become
* the installed spooler. Otherwise, nothing can be done because the
* spooler is not installed.
******************************************************************************/
if (argc == 1)
{
spooler(root_tkn);
}
else
{
printf("ERROR: Spooler not installed.\n");
status = E$OK;
}
}
}
/*9****************************************************************************
* If any RMX errors occurred during execution, display an error
* message. Finally, exit the program.
******************************************************************************/
if (status != E$OK)
{
printf("ERROR (%04xh): Could not execute spooler command.\n",
status);
}
exit(0);
}
/*1****************************************************************************
*
* Function: command_code
*
* Summary: Searches the array of valid commands for a match on the
* given command.
*
* Invocation: code = command_code(cmnd_ptr)
*
* Inputs: cmnd_ptr (char *) - address of command to search for
*
* Outputs: code (int) - returns NOT_FOUND (-1), if the command
* was not found in the array of valid commands;
* Otherwise, the value is the code for the command.
*
******************************************************************************/
command_code(cmnd_ptr)
char *cmnd_ptr;
{
int code;
int indx;
code = NOT_FOUND;
for (indx = 0; (spooler_cmnds[indx] != NULL) &&
(code == NOT_FOUND); indx++)
{
if (strcmp(cmnd_ptr, spooler_cmnds[indx]) == 0)
{
code = indx;
}
}
return (code);
}
/*1****************************************************************************
*
* Function: spooler_commands
*
* Summary: Check for any spooler commands
*
* Invocation: spooler_state = spooler_commands(spooler_mbx)
*
* Inputs: spooler_mbx (unsigned int) - the token for the mailbox
* where spooler commands will be received.
*
* Outputs: spooler_state (int) - the current command state of the
* spooler (ie. shutdown, continue)
*
******************************************************************************/
spooler_commands(spooler_mbx)
unsigned int spooler_mbx;
{
int command;
unsigned int rsp_mbx; /* command response mailbox */
unsigned int msg_tkn; /* command message token */
unsigned int status;
struct spooler_msg_str *spooler_msg_ptr;
/*9****************************************************************************
* If a spooler shutdown is pending, then don't process any more
* commands. Otherwise, check if a spooler command message is waiting
* to be processed.
******************************************************************************/
if (spooler_state != CMND_SHUTDOWN)
{
command = CMND_CONTINUE;
msg_tkn =
rq$receive$message(spooler_mbx, NO_WAIT, &rsp_mbx, &status);
if (status == E$OK)
{
/*9****************************************************************************
* If a command message was received, get the command code from the
* message and return to message to acknowledge the command was received.
* Then, process the command
******************************************************************************/
spooler_msg_ptr = bld_ptr(msg_tkn);
command = spooler_msg_ptr->cmnd_code;
rq$send$message(rsp_mbx, msg_tkn, NO_RESP, &status);
switch (command)
{
/*9****************************************************************************
* If the command is SUSPEND, then wait until a non-SUSPEND command
* is received. If a problem occurs, shutdown the spooler.
******************************************************************************/
case CMND_SUSPEND:
{
while (command == CMND_SUSPEND)
{
msg_tkn = rq$receive$message(
spooler_mbx, WAIT_FOREVER, &rsp_mbx, &status);
if (status == E$OK)
{
spooler_msg_ptr = bld_ptr(msg_tkn);
command = spooler_msg_ptr->cmnd_code;
rq$send$message(rsp_mbx,
msg_tkn, NO_RESP, &status);
}
else
{
command = CMND_SHUTDOWN;
}
}
break;
}
/*9****************************************************************************
* Any other valid commands require no additional processing in this
* routine. They will be passed back to the main spooler code.
******************************************************************************/
case CMND_SHUTDOWN:
case CMND_CONTINUE:
case CMND_NEXTFILE:
{
break;
}
/*9****************************************************************************
* If an invalid command should get through, it will be handled like
* a CONTINUE command. Which is basically a "do nothing" command.
******************************************************************************/
default:
{
command = CMND_CONTINUE;
break;
}
}
}
/*9****************************************************************************
* Set the new state to the value of the command.
******************************************************************************/
spooler_state = command;
}
return (spooler_state);
}
/*1****************************************************************************
*
* Function: spooler
*
* Summary: The main code for the installed spooler job
*
* Invocation: spooler(root_tkn)
*
* Inputs: root_tkn (unsigned int) - the token for the root job.
* This is needed so that the spooler mailbox can be
* catalogued in the root job's object directory.
*
* Outputs: none
*
******************************************************************************/
spooler(root_tkn)
unsigned int root_tkn;
{
char buffer[128]; /* file I/O buffer */
char fname[15]; /* file name ("C" format) */
int command; /* spooler command code */
unsigned int job_tkn; /* spooler job token */
unsigned int user_tkn; /* SUPER user object token */
unsigned int dir_con; /* spooler directory connection */
unsigned int status; /* RMX condition code */
unsigned int byte_cnt; /* bytes read from file */
unsigned int spooler_mbx; /* spooler mailbox */
struct dir_entry_str dir_entry; /* RMX directory entry */
struct finfo_str file_info; /* file information data */
FILE *lp; /* FILE pointer for printer */
FILE *fp; /* FILE pointer for file */
/*9****************************************************************************
* Create and catalog the print spooler mailbox.
* NOTE: RMX uses byte count strings (first byte in string is length).
******************************************************************************/
spooler_mbx = rq$create$mailbox(FIFO_MBX, &status);
if (status == E$OK)
{
rq$catalog$object(root_tkn,
spooler_mbx, SPOOLER_MBX_NAME, &status);
}
if (status != E$OK)
{
printf("ERROR (%04xh): Could not create spooler mailbox.\n",
status);
exit(1);
}
/*9****************************************************************************
* Setup the print spooler as a SUPER user. The SUPER user can get
* access to files created by any system user.
******************************************************************************/
job_tkn = rq$get$task$tokens(THIS_JOB, &status);
if (status == E$OK)
{
user_tkn = rq$create$user(&user_ids, &status);
if (status == E$OK)
{
rq$set$default$user(job_tkn, user_tkn, &status);
}
}
if (status != E$OK)
{
printf("ERROR (%04xh): Could not setup spooler as a SUPER user.\n",
status);
exit(1);
}
/*9****************************************************************************
* Attach to the spooler directory and setup this directory as the
* default directory for future file accessing.
* NOTE: RMX uses byte count strings (first byte in string is length).
******************************************************************************/
dir_con = rq$s$attach$file(spooler_dir, &status);
if (status == E$OK)
{
rq$set$default$prefix(job_tkn, dir_con, &status);
}
if (status != E$OK)
{
printf("ERROR (%04xh): Could not setup %s as spooler directory.\n",
status, &spooler_dir[1]);
exit(1);
}
/*9****************************************************************************
* Attach the system printer.
******************************************************************************/
lp = fopen(PRINTER_NAME, "w");
if (lp == NULL)
{
printf("ERROR: Could not attach the system printer\n");
exit(1);
}
/*9****************************************************************************
* Begin processing files that appear in the spooler directory until
* a shutdown command is received. Each execution of this loop represents
* one complete pass through the spooler directory's "directory file".
* The directory file contains an entry for each file in the directory.
* It also may contain empty entries from delete files. At the end of
* each pass, the directory file is closed. Spooler commands are check
* for at various points.
******************************************************************************/
command = spooler_commands(spooler_mbx);
while ((status == E$OK) && (command != CMND_SHUTDOWN))
{
rq$s$open(dir_con, READ_ONLY, BUFFERS_TWO, &status);
if (status == E$OK)
{
/*9****************************************************************************
* Process directory entries until no more entries are found.
******************************************************************************/
byte_cnt = rq$s$read$move(dir_con,
&dir_entry, sizeof(dir_entry), &status);
command = spooler_commands(spooler_mbx);
while ((byte_cnt == sizeof(dir_entry)) &&
(command == CMND_CONTINUE))
{
/*9****************************************************************************
* Copy the file name into a local buffer and convert it to a C string.
* If the entry is not empty (file node value is non-zero), then permit
* complete access to the file (Delete, Read, Append, Update). It is
* possible that the file could still be in the process of being copied to
* the spooler directory, so wait until there a no users connected with the
* file.
******************************************************************************/
strncpy(fname, dir_entry.fname, (sizeof(fname) - 1));
fname[sizeof(fname) - 1] = NUL;
if (dir_entry.fnode != 0)
{
faccess(fname, USER_SUPER, ACCESS_DRAU);
status = finfo(fname, &file_info);
if (status == E$OK)
{
while (file_info.number_connections > 0)
{
rq$sleep(WAIT_ONE_SEC, &status);
finfo(fname, &file_info);
}
/*9****************************************************************************
* Open the file, send a formfeed to the printer and begin copying the
* file to the printer. Spooler commands will be checked for as each buffer
* of data is transfered to the printer. A command other than CONTINUE, will
* terminate the printing of the file. When printing if finish, possibly
* due to a command, the file is close, the printer buffer flushed, and the
* file deleted from the spooler directory.
******************************************************************************/
fp = fopen(fname, "r");
if (fp != NULL)
{
fputc(FF, lp);
byte_cnt = fread(buffer, 1, sizeof(buffer), fp);
command =
spooler_commands(spooler_mbx);
while ((byte_cnt > 0) &&
(command == CMND_CONTINUE))
{
fwrite(buffer, 1, byte_cnt, lp);
byte_cnt =
fread(buffer, 1, sizeof(buffer), fp);
command = spooler_commands(spooler_mbx);
}
fclose(fp);
fflush(lp);
fdelete(fname);
}
}
}
byte_cnt = rq$s$read$move(dir_con,
&dir_entry, sizeof(dir_entry), &status);
command = spooler_commands(spooler_mbx);
}
rq$s$close(dir_con, &status);
}
rq$sleep(WAIT_TWO_SEC, &status);
command = spooler_commands(spooler_mbx);
}
/*9****************************************************************************
* Spooler is being shutdown so cleanup before exiting.
******************************************************************************/
rq$s$delete$connection(dir_con, &status);
rq$uncatalog$object(root_tkn, SPOOLER_MBX_NAME, &status);
rq$delete$mailbox(spooler_mbx, &status);
fclose(lp);
exit(0);
}